using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Data;
using ResourceBlender_Express.Properties;
using System.Data.Common;
using System.ComponentModel;

namespace ResourceBlender_Express {
    /// <summary>
    /// A window for managing applications
    /// </summary>
    public partial class WinApplications : Window {
        private BackgroundWorker worker;
        /// <summary>
        /// Initializes a new <see cref="WinApplications"/>.
        /// </summary>
        public WinApplications() {
            InitializeComponent();
            lstApplications.Items.SortDescriptions.Add(new System.ComponentModel.SortDescription("ApplicationName", System.ComponentModel.ListSortDirection.Ascending));
        }

        /// <summary>
        /// Loads the list of applications.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void Window_Loaded(object sender, RoutedEventArgs e) {
            LoadApplications();
        }

        /// <summary>
        /// Refreshed the list of applications.
        /// </summary>
        private void LoadApplications() {
            worker = new BackgroundWorker();
            worker.DoWork += (s, dwe) => {
                Database db = new Database();
                try {
                    dwe.Result = db.LoadApplications(true);
                } catch(Exception ex) {
                    dwe.Result = "Error connecting to the database: " + ex.Message;
                } finally {
                    if(db != null) {
                        try {
                            db.CloseConnection();
                        } catch { }
                    }
                }
            };
            worker.RunWorkerCompleted += (s, rwe) => {
                SetStatus(null, false);
                if(rwe.Result != null && rwe.Result is string) {
                    DialogBox.Show(this, rwe.Result.ToString(), "Database Error", DialogBox.DialogBoxType.OK, DialogBox.DialogBoxIcon.Error);
                } else {
                    DataContext = rwe.Result as List<RBApplication>;
                }
            };
            SetStatus("Loading applications...", true);
            worker.RunWorkerAsync();
        }

        /// <summary>
        /// Shows a window to add a new application.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void AddApplication(object sender, ExecutedRoutedEventArgs e) {
            WinAddApplication dlg = new WinAddApplication();
            dlg.Owner = this;
            if(dlg.ShowDialog() == true) {
                LoadApplications();
            }
        }

        /// <summary>
        /// Determines whether the edit application command can be executed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.CanExecuteRoutedEventArgs"/> instance containing the event data.</param>
        private void CanExecuteEditApplication(object sender, CanExecuteRoutedEventArgs e) {
            e.CanExecute = lstApplications != null && lstApplications.SelectedItem != null && (worker == null || !worker.IsBusy);
            e.Handled = true;
        }

        /// <summary>
        /// Shows a window to edit an application.
        /// </summary>
        private void EditApplication(object sender, RoutedEventArgs e) {
            if(lstApplications.SelectedValue == null)
                return;
            RBApplication originalApp = lstApplications.SelectedValue as RBApplication;
            WinAddApplication dlg = new WinAddApplication(originalApp.Clone());
            dlg.Owner = this;
            if(dlg.ShowDialog() == true) {
                LoadApplications();
            }
        }

        /// <summary>
        /// Determines whether the delete application command can be executed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.CanExecuteRoutedEventArgs"/> instance containing the event data.</param>
        private void CanExecuteDeleteApplication(object sender, CanExecuteRoutedEventArgs e) {
            e.CanExecute = lstApplications != null && lstApplications.SelectedItem != null && (worker == null || !worker.IsBusy);
            e.Handled = true;
        }

        /// <summary>
        /// Deletes an application after the user has confirmed.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void DeleteApplication(object sender, ExecutedRoutedEventArgs e) {
            if(lstApplications.SelectedValue == null)
                return;
            RBApplication app = lstApplications.SelectedValue as RBApplication;
            if(DialogBox.Show(this, string.Format("Are you sure you want to delete the application '{0}'?{1}{1} All bundles and elements contained within this application will also be deleted. Translations, will be not be deleted.", app.DisplayName, Environment.NewLine), "Confirm Delete", DialogBox.DialogBoxType.YesNo, DialogBox.DialogBoxIcon.Question) == DialogBox.DialogBoxButton.Yes) {
                worker = new BackgroundWorker();
                worker.DoWork += (s, dwe) => {
                    dwe.Result = DeleteApplication(app);  
                };
                worker.RunWorkerCompleted += (s, rwe) => {
                    SetStatus(null, false);
                    if(rwe.Result != null) {
                        DialogBox.Show(this, rwe.Result.ToString(), "Database Error", DialogBox.DialogBoxType.OK, DialogBox.DialogBoxIcon.Error);
                    }
                    LoadApplications();
                };
                SetStatus("Deleting application...", true);
                worker.RunWorkerAsync();
            }
        }

        /// <summary>
        /// Deletes an application <b>synchronously</b> from the database. Does not show a prompt to confirm.
        /// </summary>
        /// <param name="application">The application to delete.</param>
        /// <returns><c>null</c> unless an error is encountered</returns>
        public static string DeleteApplication(RBApplication application) {
            string result = null;
            Database db = new Database();
            try {
                db.OpenConnection();
                using(Database.Command cmd = db.CreateCommand()) {
                    cmd.CommandText = "DELETE FROM " + db.TablePrefix + "applications WHERE id = @p";
                    cmd.AddParameterWithValue("@p", application.ID);
                    cmd.ExecuteNonQuery();
                    cmd.CommandText = "DELETE FROM " + db.TablePrefix + "bundles WHERE application = @p";
                    cmd.ExecuteNonQuery();
                    cmd.CommandText = "DELETE FROM " + db.TablePrefix + "elements WHERE applicationid = @p";
                    cmd.ExecuteNonQuery();
                }
            } catch(Exception ex) {
                result = "Error connecting to the database: " + ex.Message;
            } finally {
                if(db != null) {
                    try {
                        db.CloseConnection();
                    } catch { }
                }
            }
            return result;
        }

        /// <summary>
        /// Closes the window.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void CloseWindow(object sender, ExecutedRoutedEventArgs e) {
            DialogResult = true;
            Close();
        }

        /// <summary>
        /// Sets the text on the status message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="showProgress"><c>true</c> if the progress bar should be shown, otherwise <c>false</c>.</param>
        private void SetStatus(string message, bool showProgress) {
            prgStatus.Visibility = showProgress ? Visibility.Visible : Visibility.Hidden;
            if(message == null) {
                lblStatus.Visibility = Visibility.Hidden;
            } else {
                lblStatus.Visibility = Visibility.Visible;
                lblStatus.Content = message;
            }
        }
    }
}
